{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "MMDAutoTrace4.00.02.ipynb",
      "provenance": [],
      "gpuType": "T4",
      "toc_visible": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "source": [
        "# Colab版MMD自動トレースv4 へようこそ！(実行編)"
      ],
      "metadata": {
        "id": "Fyy5ukQ1Snmq"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 始めに\n",
        "\n",
        "このツールの稼働状況やメンテナンス情報はTwitter（[@miu200521358](https://twitter.com/miu200521358)）にて行っています。\n",
        "\n",
        "エラーになる、起動しない、などの場合、まずは現在の配布状況をご確認ください。\n",
        "\n",
        "メンテ中以外でうまくいかない場合などのご相談はコミュニティの掲示板もしくはノートブックの共有からお願いします。\n",
        "\n",
        "https://discord.gg/HEuvWV2v7G"
      ],
      "metadata": {
        "id": "x0Du9XXeSsPi"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 目次\n",
        "\n",
        "このノートブックでは、MMD自動トレースの準備と実行を行います\n",
        "\n",
        "ノートブックの使い方にはクセがあるので、「[準備編](https://colab.research.google.com/github/miu200521358/motion_trace_colab/blob/develop/MMDAutoTraceIntroduction.ipynb)」で使い方に慣れてください\n",
        "\n",
        "画面左上の「＝」（実際は三本線）をクリックして下さい。目次が開きます（既に開いている場合は次へ進んでください）\n",
        "\n",
        "![目次](https://drive.google.com/uc?export=view&id=1HGk4sJmcPtMbMwcJOvE3aU1GjvKinwA_)\n",
        "\n",
        "Googleドライブの直下に`autotrace`フォルダを作成してください\n",
        "\n",
        "（準備編で既に作られている場合は再作成不要です）\n",
        "\n",
        "ノートブックを上から順に確認し、以下手順をひとつずつ実行してください\n",
        "\n",
        "実行が必要なセルには番号を振ってあります。①から順番に実行してください\n",
        "\n",
        "- **「①　環境構築」**\n",
        "  - MMD自動トレースv4 用の環境を構築します。\n",
        "- **「②　MMD自動トレースv4 実行」**\n",
        "    - MMD自動トレースv4 を実行します。\n"
      ],
      "metadata": {
        "id": "CoaXwL-ASx6q"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 起こる可能性のあるエラー・警告と対処方法"
      ],
      "metadata": {
        "id": "f-XzbSo-TgtU"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## GPU上限突破"
      ],
      "metadata": {
        "id": "aEQ4dKwATlsr"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "下記のようなエラーが出た場合、GPUの使用量上限に達しました\n",
        "\n",
        "無料域の場合、24時間以上待っていただくと再度利用できるようになります\n",
        "\n",
        "![上限](https://drive.google.com/uc?export=view&id=1xxg5yM-wgNkAr1FboAM8DS2K-aqmtw5d)\n",
        "\n",
        "再度使えるようになったか確認するには、右上の「接続」アイコンをクリックしてください\n",
        "\n",
        "まだ使えない場合、再度上記ダイアログが出てきます\n",
        "\n",
        "接続できたらGPUが再び使用できるようになっています\n",
        "\n",
        "使える時間数は接続が完了した後のサイド画面で確認出来ます\n",
        "\n",
        "![上限](https://drive.google.com/uc?export=view&id=1o0m1dklnk9JFTqsAmkLFa8McvfUaMmqe)\n"
      ],
      "metadata": {
        "id": "Ma1e14jVToVi"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 環境のクラッシュ"
      ],
      "metadata": {
        "id": "NrT6jPFBTq_x"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "下記のようなエラーが出た場合、環境がクラッシュしました\n",
        "\n",
        "セッションを一度削除して、環境を作り直してください\n",
        "\n",
        "![クラッシュ](https://drive.google.com/uc?export=view&id=1qMoxfUggI_jDjrDifj7UgOrSmsEOMmHY)\n",
        "\n",
        "![クラッシュ](https://drive.google.com/uc?export=view&id=1WFHmCzEkCLi8XnHyl7goicNQPL67RHhX)\n",
        "\n",
        "![削除](https://drive.google.com/uc?export=view&id=12UaonO4UvI_HCnJI95od15_yagVIVsRD)\n",
        "\n",
        "![削除](https://drive.google.com/uc?export=view&id=1smRW97KjP8fqSy3E5dtfWJHpyBtEMKca)\n"
      ],
      "metadata": {
        "id": "TYONV48qTtSf"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 環境の自動削除"
      ],
      "metadata": {
        "id": "n0N0LWYnTw0k"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "下記のようなエラーが出た場合、時間経過や上記クラッシュなどによりColabから環境が既に破棄されています\n",
        "\n",
        "セッションを一度削除して、環境を作り直してください\n",
        "\n",
        "![Googleドライブ連携](https://drive.google.com/uc?export=view&id=1Oa5SNwStqzR6qVMEzxg8PdLmO3FTpr1l)\n"
      ],
      "metadata": {
        "id": "ywNefafZTyy8"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## GPU未使用警告"
      ],
      "metadata": {
        "id": "P-eZr-2ST1bk"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "作業中に下記のような警告が出ることがありますが、【②-C】以外はそのまま進めていただいて問題ありません\n",
        "\n",
        "　（GPUを使うのはAIを実行する箇所だけですので、その他のセルを作業中に出る可能性があります）\n",
        "\n",
        "![警告](https://drive.google.com/uc?export=view&id=1mRW32urnPQ4LS4xrLEoPdp_XCqlq1HUF)\n"
      ],
      "metadata": {
        "id": "v28ncAfzT3db"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## ディスク容量残警告"
      ],
      "metadata": {
        "id": "uH6cRFVgmfh4"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "下記のような警告が出てきたら、1回目は無視して大丈夫です\n",
        "\n",
        "2回目が出てきたら、途中でディスクがパンクする恐れがあるため、入力映像をキリのいいところで区切って分けて処理してください"
      ],
      "metadata": {
        "id": "cUxpejEEmlKM"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "\n",
        "![容量オーバー](https://drive.google.com/uc?export=view&id=1EKt3nCK6ZYjgkNoflQNzSnW_0s4WnJYO)\n",
        "\n"
      ],
      "metadata": {
        "id": "Hae7pvkCmdps"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## インタラクティブな使用の確認"
      ],
      "metadata": {
        "id": "mec-tc5_jpd-"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "下記のような確認が出てきたら、「私はロボットではありません」のチェックを入れてください\n",
        "\n",
        "Colabでは長時間（90分ほど）操作しないとこのダイアログが出てしまいます"
      ],
      "metadata": {
        "id": "ccwq3sUfjqrs"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "\n",
        "![確認](https://drive.google.com/uc?export=view&id=1tuioznet4aC-RBtiuKrohxbQqeEvCYBU)\n",
        "\n"
      ],
      "metadata": {
        "id": "cHMC3jWmjsto"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 利用規約"
      ],
      "metadata": {
        "id": "tUNmRfXodyvM"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "MMD自動トレースをご利用、またはその結果を公開・配布する場合は、必ず利用規約のご確認をお願い致します\n",
        "\n",
        "JSONデータの利用やUnityへの適用等、MMD以外での使用の場合も同様です\n",
        "\n",
        "[MMD自動トレースv4 利用規約](https://github.com/miu200521358/mmd-auto-trace-4/wiki/03.%E5%88%A9%E7%94%A8%E8%A6%8F%E7%B4%84)\n",
        "\n",
        "[MMD自動トレースv4 使用技術・ライセンス](https://github.com/miu200521358/mmd-auto-trace-4/wiki/02.%E4%BD%BF%E7%94%A8%E6%8A%80%E8%A1%93)"
      ],
      "metadata": {
        "id": "UqHhDeUAUA3V"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "# ①　環境構築"
      ],
      "metadata": {
        "id": "cGNYDeTFeFWW"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## ①-A　通知音のダウンロード\n",
        "\n",
        "通知音を[効果音ラボ](https://soundeffect-lab.info/)様よりダウンロードして、セルの実行を開始・完了・失敗、および全ての処理が完了した時に音が鳴るようにします\n",
        "\n",
        "下の【①-A】のセルを実行してください\n",
        "\n",
        "ダウンロードが完了すると、再生ボタンが表示されますので、それぞれの音を確認しておいてください\n",
        "\n"
      ],
      "metadata": {
        "id": "c2wqFlb4eTe2"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "#@markdown 【①-A】　通知音のダウンロード\n",
        "\n",
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "from enum import Enum\n",
        "\n",
        "class SoundType(Enum):\n",
        "    START = 0\n",
        "    SUCCESS = 1\n",
        "    FAIL = 2\n",
        "    COMPLETE = 3\n",
        "\n",
        "# ----------------------------------\n",
        "\n",
        "! wget --no-check-certificate -c \"https://soundeffect-lab.info/sound/anime/mp3/sceneswitch1.mp3\"\n",
        "! wget --no-check-certificate -c \"https://soundeffect-lab.info/sound/anime/mp3/incorrect1.mp3\"\n",
        "! wget --no-check-certificate -c \"https://soundeffect-lab.info/sound/anime/mp3/switch1.mp3\"\n",
        "! wget --no-check-certificate -c \"https://soundeffect-lab.info/sound/anime/mp3/trumpet1.mp3\"\n",
        "\n",
        "from IPython.display import Audio, display\n",
        "import torch\n",
        "\n",
        "def play_sound(sound_type: SoundType, autoplay=True):\n",
        "    try:\n",
        "        if sound_type == SoundType.START:\n",
        "            file_name = \"/content/switch1.mp3\"\n",
        "        elif sound_type == SoundType.SUCCESS:\n",
        "            file_name = \"/content/sceneswitch1.mp3\"\n",
        "        elif sound_type == SoundType.COMPLETE:\n",
        "            file_name = \"/content/trumpet1.mp3\"\n",
        "        else:\n",
        "            file_name = \"/content/incorrect1.mp3\"\n",
        "\n",
        "        display(Audio(file_name, autoplay=autoplay, normalize=False))\n",
        "    except:\n",
        "        print(\"■■■■■■■■■■■■■■■\")\n",
        "        print(\"■　効果音が再生できませんでした\")\n",
        "        print(\"■■■■■■■■■■■■■■■\")\n",
        "\n",
        "# ----------------------------------\n",
        "\n",
        "exec_dict = {\n",
        "    '①-A': {'exec': False, 'premise': []},\n",
        "    '①-B': {'exec': False, 'premise': ['①-A', ]},\n",
        "    '①-C': {'exec': False, 'premise': ['①-A', '①-B', ]},\n",
        "    '①-D': {'exec': False, 'premise': ['①-A', '①-B', '①-C', ]},\n",
        "    '①-E': {'exec': False, 'premise': ['①-A', '①-B', '①-C', '①-D', ]},\n",
        "    '①-F': {'exec': False, 'premise': ['①-A', '①-B', '①-C', '①-D', '①-E', ]},\n",
        "    '②-A': {'exec': False, 'premise': ['①-A', '①-B', '①-C', '①-D', '①-E', '①-F', ]},\n",
        "    '②-B': {'exec': False, 'premise': ['①-A', '①-B', '①-C', '①-D', '①-E', '①-F', '②-A' ]},\n",
        "    '②-C': {'exec': False, 'premise': ['①-A', '①-B', '①-C', '①-D', '①-E', '①-F', '②-A', '②-B' ]},\n",
        "}\n",
        "\n",
        "NVIDIA_VISIBLE_DEVICES=all\n",
        "\n",
        "class IpyExit(SystemExit):\n",
        "    def __init__(self, text: str = None):\n",
        "        if text:\n",
        "            print(\"■■■■■■■■■■■■■■■\")\n",
        "            print(\"■　** ERROR **\")\n",
        "            print(f\"■　{text}\")\n",
        "            print(\"■■■■■■■■■■■■■■■\")\n",
        "        play_sound(SoundType.FAIL)\n",
        "        pass\n",
        "\n",
        "def check_exec_dict(cell_key: str, is_cpu=False):\n",
        "    if not is_cpu and not torch.cuda.is_available():\n",
        "        print(\"■■■■■■■■■■■■■■■\")\n",
        "        print(\"■　** ERROR **\")\n",
        "        print(\"■　GPUが有効になってません。\")\n",
        "        print(\"■　準備編を参考にしながらランタイムをGPUに変更してください。\")\n",
        "        print(\"■■■■■■■■■■■■■■■\")\n",
        "        raise IpyExit\n",
        "\n",
        "    if not exec_dict:\n",
        "        print(\"■■■■■■■■■■■■■■■\")\n",
        "        print(\"■　** ERROR **\")\n",
        "        print(\"■　セル【①-A】が実行されていない可能性があります。\")\n",
        "        print(\"■　目次から戻って実行してください。\")\n",
        "        print(\"■■■■■■■■■■■■■■■\")\n",
        "        raise IpyExit\n",
        "\n",
        "    for p in exec_dict[cell_key]['premise']:\n",
        "        # 事前に実行されるべきセルがすべて実行されているか\n",
        "        if not exec_dict[p]['exec']:\n",
        "            print(\"■■■■■■■■■■■■■■■\")\n",
        "            print(\"■　** ERROR **\")\n",
        "            print(f\"■　セル【{p}】が実行されていない可能性があります。\")\n",
        "            print(\"■　目次から戻って実行してください。\")\n",
        "            print(\"■■■■■■■■■■■■■■■\")\n",
        "            raise IpyExit\n",
        "\n",
        "    # 全部実行されていたらOK\n",
        "    play_sound(SoundType.START)\n",
        "    return True\n",
        "\n",
        "def finish_cell(cell_key: str):\n",
        "    play_sound(SoundType.SUCCESS)\n",
        "\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    print(\"■　** OK **\")\n",
        "    print(f\"■　セル【{cell_key}】の実行に成功しました。\")\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "\n",
        "    exec_dict[cell_key]['exec'] = True\n",
        "\n",
        "# ----------------------------------\n",
        "\n",
        "# セル実行可否\n",
        "ckey = \"①-A\"\n",
        "check_exec_dict(ckey)\n",
        "\n",
        "# ----------------------------------\n",
        "\n",
        "# セル終了\n",
        "\n",
        "finish_cell(ckey)\n",
        "\n",
        "print(\"\")\n",
        "print(\"\")\n",
        "print(\"■ セル実行開始\")\n",
        "play_sound(SoundType.START, autoplay=False)\n",
        "\n",
        "print(\"\")\n",
        "print(\"\")\n",
        "print(\"■ セル実行失敗\")\n",
        "play_sound(SoundType.FAIL, autoplay=False)\n",
        "\n",
        "print(\"\")\n",
        "print(\"\")\n",
        "print(\"■ セル実行成功\")\n",
        "play_sound(SoundType.SUCCESS, autoplay=False)\n",
        "\n",
        "print(\"\")\n",
        "print(\"\")\n",
        "print(\"■ 自動トレース全て完了\")\n",
        "play_sound(SoundType.COMPLETE, autoplay=False)"
      ],
      "metadata": {
        "cellView": "form",
        "id": "ENPQ2HkzeZdl"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## ①-B　GPUランタイムの確認\n",
        "\n",
        "ヘッダの \"ランタイム\"　＞　\"ランタイムのタイプを変更\"　＞　\"GPU\"　を選択して下さい\n",
        "\n",
        "詳しい手順は、「[MMD自動トレース 準備編](https://colab.research.google.com/github/miu200521358/motion_trace_colab/blob/master/AutoTraceIntroduction.ipynb)」を参考にしてください\n",
        "\n",
        "変更できたら、下の【①-B】のセルを実行して下さい"
      ],
      "metadata": {
        "id": "WKqIyaMoe2wP"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "#@markdown 【①-B】　GPUランタイムの確認\n",
        "\n",
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "# セル実行可否\n",
        "ckey = \"①-B\"\n",
        "check_exec_dict(ckey)\n",
        "\n",
        "# ----------------------------------\n",
        "\n",
        "# OSバージョンとかもログに出す\n",
        "! cat /etc/os-release\n",
        "\n",
        "! nvidia-smi\n",
        "\n",
        "import subprocess\n",
        "try:\n",
        "    subprocess.check_output(\"nvidia-smi\", shell=True)\n",
        "except:\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    print(\"■　** ERROR **\")\n",
        "    print(\"■　nvidia-smiコマンドの実行に失敗しました。\")\n",
        "    print(\"■　① まだGPUを使ってない場合、ランタイムの設定を行っていない場合\")\n",
        "    print(\"■　　準備編を参考にしながら、ランタイムをGPUに設定してください\")\n",
        "    print(\"■　　※ランタイムを変更すると環境がリセットされるため、【①-A】からやり直してください\")\n",
        "    print(\"■　② GPUの利用上限に達して、CPUでしか使えない場合\")\n",
        "    print(\"■　　無料域の場合、24時間以上置いていただくと再度使用できるようになります\")\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "\n",
        "# ----------------------------------\n",
        "\n",
        "# セル終了\n",
        "finish_cell(ckey)"
      ],
      "metadata": {
        "cellView": "form",
        "id": "_dGYRo6Me7Df"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## ①-C　Googleドライブとの連携\n",
        "\n",
        "下記目的のため、このColabページからあなたのGoogleドライブにアクセスする許可を与えてください\n",
        " - Googleドライブに保存されたトレース元動画を読み取る為\n",
        " - 自動トレース結果を保存する為\n",
        "\n",
        "※Googleドライブ内の「autotrace」フォルダ以外は触りません\n",
        "\n",
        "下の【①-C】のセルを実行して、サブウィンドウから全てのアクセス許可を付与して連携を許可してください"
      ],
      "metadata": {
        "id": "WfRS49WpfC0a"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "#@markdown 【①-C】　Googleドライブとの連携\n",
        "\n",
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "# セル実行可否\n",
        "ckey = \"①-C\"\n",
        "check_exec_dict(ckey)\n",
        "\n",
        "# ----------------------------------\n",
        "\n",
        "from google.colab import drive\n",
        "import os\n",
        "\n",
        "# Googleドライブマウント\n",
        "drive.mount('/gdrive')\n",
        "\n",
        "# 起点ディレクトリ\n",
        "base_dir_path = \"/gdrive/My Drive/autotrace\"\n",
        "\n",
        "if os.path.exists(base_dir_path):\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    print(\"■　** OK **\")\n",
        "    print(\"■　autotraceフォルダ内との連携が成功しました。\")\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "else:\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    print(\"■　** ERROR **\")\n",
        "    print(\"■　autotraceフォルダがGoogleドライブの直下に見つかりませんでした。\")\n",
        "    print(\"■　準備編を参考にしながら、autotraceフォルダを作成してください。\")\n",
        "    print(\"■　※スペルミスだった場合、ファイル名などの変更は行わず、新しいフォルダもしくはファイルで試してください。\")\n",
        "    print(\"■　　Googleドライブとの連携後の更新はうまく認識されません。\")\n",
        "    print(\"■　※少しタイムラグがあるので、修正した直後は認識されない場合があります。\")\n",
        "    print(\"■　　10秒くらい待ってからセルを再実行してください。\")\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    raise IpyExit\n",
        "\n",
        "# ----------------------------------\n",
        "\n",
        "# セル終了\n",
        "finish_cell(ckey)"
      ],
      "metadata": {
        "cellView": "form",
        "id": "QkEaktdxfcqE"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## ①-D　GoogleSDKとの連携\n",
        "\n",
        "miuのGoogleドライブから自動トレースに必要なデータをDLするため、`GoogleSDK` と連携します\n",
        "\n",
        "下の【①-D】のセルを実行して、セル【①-C】と同じく、新しく表示されたウィンドウから全てのアクセス許可を与えてください"
      ],
      "metadata": {
        "id": "TAPv-jy7fz4h"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "#@markdown 【①-D】　Google SDK との連携\n",
        "\n",
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "# セル実行可否\n",
        "ckey = \"①-D\"\n",
        "check_exec_dict(ckey)\n",
        "\n",
        "# ----------------------------------\n",
        "\n",
        "# Googleドライブアクセスライブラリ\n",
        "!pip install -U -q PyDrive2\n",
        "\n",
        "from pydrive2.auth import GoogleAuth\n",
        "from pydrive2.drive import GoogleDrive\n",
        "from google.colab import auth\n",
        "from oauth2client.client import GoogleCredentials\n",
        "\n",
        "try:\n",
        "    auth.authenticate_user()\n",
        "    gauth = GoogleAuth()\n",
        "    gauth.credentials = GoogleCredentials.get_application_default()\n",
        "    drive = GoogleDrive(gauth)\n",
        "\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    print(\"■　** OK **\")\n",
        "    print(\"■　Google SDK との連携に成功しました。\")\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "\n",
        "except Exception as e:\n",
        "    print(e.message)\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    print(\"■　** Error **\")\n",
        "    print(\"■　Google SDK との連携に失敗しました。\")\n",
        "    print(\"■　このノートブックを作者に共有してください。\")\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    raise IpyExit\n",
        "\n",
        "# ----------------------------------\n",
        "\n",
        "# セル終了\n",
        "finish_cell(ckey)"
      ],
      "metadata": {
        "cellView": "form",
        "id": "P51Ag4QigW1q"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## ①-E　コードセットアップ\n",
        "\n",
        "MMD自動トレースのコードを構築します\n",
        "\n",
        "下の【①-E】のセルを実行して下さい\n",
        "\n",
        "たくさんメッセージが出て、セル内の処理完了まで15分くらいかかります\n",
        "\n",
        "**途中でコンパイルが走るので、動かなくなったように見える箇所があります**\n",
        "\n",
        "**ビックリしたり心配になって、セルを中断しないようお願いします。そのまま待っていれば終わります**\n",
        "\n",
        "`ERROR` という文字列が出る場合もありますが、自動トレースを実行するには問題ないエラーの可能性が高いので、一旦無視してそのまま進めて下さい"
      ],
      "metadata": {
        "id": "8hXO0YvKhLa_"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "#@markdown 【①-E】　コードセットアップ\n",
        "\n",
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "# セル実行可否\n",
        "ckey = \"①-E\"\n",
        "check_exec_dict(ckey)\n",
        "\n",
        "# ----------------------------\n",
        "\n",
        "# 既存ディレクトリの削除  ---------\n",
        "! rm -r mmd-auto-trace-4\n",
        "\n",
        "# # 環境変数設定  ---------\n",
        "# ! DEBIAN_FRONTEND=noninteractive\n",
        "# ! apt-get update && apt-get install -y  -o Dpkg::Options::=\"--force-confdef\" -o Dpkg::Options::=\"--force-confold\" keyboard-configuration\n",
        "\n",
        "# # ライブラリの追加 ---------\n",
        "# ! sudo apt install libosmesa6-dev build-essential libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev gcc libyaml-dev gcc\n",
        "\n",
        "# # CUDA 11.7 のインストール ---------\n",
        "\n",
        "# ! wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-ubuntu2204.pin\n",
        "# ! sudo mv cuda-ubuntu2204.pin /etc/apt/preferences.d/cuda-repository-pin-600\n",
        "# ! wget https://developer.download.nvidia.com/compute/cuda/11.7.0/local_installers/cuda-repo-ubuntu2204-11-7-local_11.7.0-515.43.04-1_amd64.deb\n",
        "# ! sudo dpkg -i cuda-repo-ubuntu2204-11-7-local_11.7.0-515.43.04-1_amd64.deb\n",
        "# ! sudo cp /var/cuda-repo-ubuntu2204-11-7-local/cuda-*-keyring.gpg /usr/share/keyrings/\n",
        "# ! sudo apt-get update\n",
        "# !apt-get -y install cuda-11-7\n",
        "\n",
        "# # CUDAのPATHを変更 ---------\n",
        "\n",
        "# ! !ls -d /usr/local/cuda-*\n",
        "\n",
        "# import os\n",
        "# p = os.getenv('PATH')\n",
        "# ld = os.getenv('LD_LIBRARY_PATH')\n",
        "# os.environ['PATH'] = f\"/usr/local/cuda-11.7/bin:{p}\"\n",
        "# os.environ['LD_LIBRARY_PATH'] = f\"/usr/local/cuda-11.7/lib64:{ld}\"\n",
        "\n",
        "# 再確認ログ ---------\n",
        "! nvcc --version\n",
        "\n",
        "# MMD自動トレースv4 clone  ---------\n",
        "version_tag = \"v4.0.2\"\n",
        "# version_tag = \"fix-requirements\"\n",
        "\n",
        "! git clone  --recursive --depth 1 -b \"$version_tag\" \"https://github.com/miu200521358/mmd-auto-trace-4.git\"\n",
        "\n",
        "# # PyTorchのインストール ---------\n",
        "# ! python -m pip install numpy==1.24.2\n",
        "# ! python -m pip install torch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2\n",
        "\n",
        "# ライブラリのインストール ---------\n",
        "! python -m pip install torch\n",
        "! python -m pip install -e .[all]\n",
        "! python -m pip install -r /content/mmd-auto-trace-4/requirements.txt\n",
        "\n",
        "# ----------------------------\n",
        "\n",
        "# セル終了\n",
        "finish_cell(ckey)"
      ],
      "metadata": {
        "id": "Wm_DfN5bhaCl",
        "cellView": "form"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## ①-F　データ配置\n",
        "\n",
        "MMD自動トレースに必要なデータを配置します\n",
        "\n",
        "下の【①-F】のセルを実行して下さい"
      ],
      "metadata": {
        "id": "0wpzqPQ4ihVn"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "#@markdown 【①-F】　データ配置\n",
        "\n",
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "# セル実行可否\n",
        "ckey = \"①-F\"\n",
        "check_exec_dict(ckey)\n",
        "\n",
        "!mkdir -p '/content/mmd-auto-trace-4/data/'\n",
        "\n",
        "# ----------------------------\n",
        "\n",
        "# basicModel_neutral_lbs_10_207_0_v1.0.0.pkl\n",
        "downloaded = drive.CreateFile({'id': '1wWDlhqrQsp9j0MpOYF6FCmMmgdxI53M6'})\n",
        "downloaded.GetContentFile('/content/mmd-auto-trace-4/data/basicModel_neutral_lbs_10_207_0_v1.0.0.pkl')\n",
        "\n",
        "! mkdir -p '/content/mmd-auto-trace-4/cache/phalp/3D/models/smpl'\n",
        "! cp '/content/mmd-auto-trace-4/data/basicModel_neutral_lbs_10_207_0_v1.0.0.pkl' '/content/mmd-auto-trace-4/cache/phalp/3D/models/smpl/SMPL_NEUTRAL.pkl'\n",
        "\n",
        "# # pose_landmarker_full.task\n",
        "# downloaded = drive.CreateFile({'id': '1Qyu3BB61rYSprkK-p4RswWrXcO8zyN7W'})\n",
        "# downloaded.GetContentFile('/content/mmd-auto-trace-4/data/pose_landmarker_full.task')\n",
        "\n",
        "! chmod 744 '/content/mmd-auto-trace-4/build/mat4'\n",
        "\n",
        "# ----------------------------\n",
        "\n",
        "# セル終了\n",
        "finish_cell(ckey)"
      ],
      "metadata": {
        "cellView": "form",
        "id": "VGB11PgjisJ1"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "# ②　MMD自動トレースv4 実行"
      ],
      "metadata": {
        "id": "5ek2ZWYJkMqb"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## ②-A　トレース元動画配置\n",
        "\n",
        "トレースを行いたい動画ファイルを準備してください\n",
        "\n",
        "- ファイル名は **半角英数字のみ** にしてください。opencvは2バイト文字を読み込めません\n",
        "- 1人の動画30秒（30fpsの1000F）につき、**1時間** ほどかかります\n",
        "   - 大体3時間が無料枠で使える1日あたりの上限となります\n",
        "   - 【②-C】を繰り返し最後まで実行すればモーションデータが生成されます\n",
        "- Googleドライブの **autotrace** フォルダ 直下に置いてください\n",
        "- **マウント後のGooleドライブ上のファイルの上書きや更新は正しく認識されません**\n",
        "    - 新しいファイルはこれまでとは違う名前でアップロードしてから処理して下さい\n",
        "- 入力するのは、ファイル名（拡張子含む）のみです\n",
        "- ファイルをアップロードできたら、下の【②-A】のセルを実行して下さい\n",
        "- 最初に試される場合は、短い動画で確認してください\n",
        "    - 動画を最後までトレースしないと、モーションデータが作成できません"
      ],
      "metadata": {
        "id": "30ajJ1K3kW69"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "#@markdown 【②-A】　トレース元動画配置\n",
        "\n",
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "# セル実行可否\n",
        "ckey = \"②-A\"\n",
        "check_exec_dict(ckey)\n",
        "\n",
        "# ----------------------------\n",
        "\n",
        "input_video_name = \"input.mp4\"  #@param {type: \"string\"}\n",
        "\n",
        "import os, shutil\n",
        "input_drive_video_path = os.path.join(base_dir_path, input_video_name)\n",
        "input_video_path = \"/content/hoge.mp4\"\n",
        "\n",
        "if not os.path.exists(input_drive_video_path):\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    print(\"■　** ERROR **\")\n",
        "    print(\"■　autotrace 直下に 指定動画 が見つかりませんでした。\")\n",
        "    print(\"■　・マイドライブ > 「autotrace」フォルダ > 指定画像 の順番でファイルが配置されているか再確認してください\")\n",
        "    print(\"■　・配置した直後だと、認識が間に合わない場合がありますので、10秒ほど待ってから再度実行してください\")\n",
        "    print(\"■　ファイルパス: \" + input_drive_video_path)\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    raise IpyExit\n",
        "else:\n",
        "    shutil.copy(input_drive_video_path, \"/content/\")\n",
        "\n",
        "    input_video_path = f\"/content/{input_video_name}\"\n",
        "\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    print(\"■　** OK **\")\n",
        "    print(\"■　トレース元動画の配置が完了しました。\")\n",
        "    print(\"■　ファイルパス: \" + input_video_path)\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "\n",
        "\n",
        "# ----------------------------\n",
        "\n",
        "# セル終了\n",
        "finish_cell(ckey)"
      ],
      "metadata": {
        "cellView": "form",
        "id": "625x35Vaky9I"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## ②-B　トレース作業フォルダ配置\n",
        "\n",
        "前日以前に自動トレースを実行していて、途中で無料枠を使い切ってしまっていた場合、Googleドライブ上の作業フォルダを指定することでトレースを再開できます\n",
        "\n",
        "- フォルダ名は `autotrace` フォルダの中にある もっとも新しいフォルダ名を指定してください\n",
        "- 新しくトレースを開始したい場合、フォルダ名は空欄のままにしてください\n",
        "- 新規開始および再開のいずれの場合も、下の【②-B】のセルを実行して下さい"
      ],
      "metadata": {
        "id": "tbR3A1f8cCBJ"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "#@markdown 【②-B】　トレース作業フォルダ配置\n",
        "\n",
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "# セル実行可否\n",
        "ckey = \"②-B\"\n",
        "check_exec_dict(ckey)\n",
        "\n",
        "# ----------------------------\n",
        "\n",
        "process_dir_name = \"\"  #@param {type: \"string\"}\n",
        "\n",
        "import os\n",
        "import shutil\n",
        "process_dir_path = os.path.join(base_dir_path, process_dir_name)\n",
        "\n",
        "if not process_dir_name:\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    print(\"■　** OK **\")\n",
        "    print(\"■　トレース作業フォルダが指定されていないため、新規にトレースを開始します\")\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "else:\n",
        "    if not os.path.exists(process_dir_path):\n",
        "        print(\"■■■■■■■■■■■■■■■\")\n",
        "        print(\"■　** ERROR **\")\n",
        "        print(\"■　autotrace 直下に 指定フォルダ が見つかりませんでした。\")\n",
        "        print(\"■　・マイドライブ > 「autotrace」フォルダ の中のフォルダが名が指定できているか確認してください\")\n",
        "        print(\"■　フォルダパス: \" + process_dir_path)\n",
        "        print(\"■■■■■■■■■■■■■■■\")\n",
        "        raise IpyExit\n",
        "    else:\n",
        "        shutil.copytree(process_dir_path, f\"/content/output/{process_dir_name}\", dirs_exist_ok=True)\n",
        "\n",
        "        process_dir_path = f\"/content/output/{process_dir_name}\"\n",
        "\n",
        "        print(\"■■■■■■■■■■■■■■■\")\n",
        "        print(\"■　** OK **\")\n",
        "        print(\"■　トレース作業フォルダの配置が完了しました。\")\n",
        "        print(\"■　フォルダパス: \" + process_dir_path)\n",
        "        print(\"■■■■■■■■■■■■■■■\")\n",
        "\n",
        "# ----------------------------\n",
        "\n",
        "# セル終了\n",
        "finish_cell(ckey)"
      ],
      "metadata": {
        "cellView": "form",
        "id": "tpkiKYKScuzQ"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## ②-C　MMD自動トレースv4\n",
        "\n",
        "トレース元動画に対して、MMD自動トレースを実行します\n",
        "\n",
        "トレース作業フォルダが指定されていた場合、MMD自動トレースを再開します\n",
        "\n",
        "Googleドライブの `autotrace` フォルダに新しいフォルダを作成して、各ステップごとの結果を保存します\n",
        "\n",
        "経過時間等のメッセージが出ない場合がありますが、実行が中断されなければトレース作業は開始されていますので、セルを中断しないでください\n",
        "\n",
        "Colabの時間制限に対応するため、1000Fごとにセルの実行を完了して音（木琴）を鳴らします\n",
        "\n",
        "途中でセルの実行が完了した場合、vmdデータはまだ作成しません。代わりにpklファイルのみ保存します\n",
        "\n",
        "全てのトレース作業完了音（ラッパのファンファーレ）が鳴るまで、【②-C】のセルを何度も実行してください\n",
        "\n",
        "一回のトレースで処理するフレーム数を「block_frame_num」で調整出来ます\n",
        "\n",
        "トレース人数が4人以上の場合、1000 だと処理時間オーバーしてしまう場合があるので 800 位に抑えると安全です\n",
        "\n",
        "それ以下の場合はそのままで問題ありません\n",
        "\n",
        "無料枠の場合、大体3時間程度が1日の利用上限となっています"
      ],
      "metadata": {
        "id": "9Tinu8_mlnzN"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "#@markdown 【②-C】　MMD自動トレースv4 実行\n",
        "\n",
        "#@markdown ■■■■■■■■■■■■■■■■■■\n",
        "\n",
        "# セル実行可否\n",
        "ckey = \"②-C\"\n",
        "check_exec_dict(ckey)\n",
        "\n",
        "block_frame_num = 1000  #@param {type: \"number\"}\n",
        "\n",
        "# ----------------------------\n",
        "\n",
        "%cd /content/mmd-auto-trace-4\n",
        "\n",
        "import datetime\n",
        "import os\n",
        "import shutil\n",
        "from glob import glob\n",
        "import os\n",
        "\n",
        "if not os.path.exists(input_video_path):\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    print(\"■　** ERROR **\")\n",
        "    print(\"■　ファイルのコピーに失敗しています。\")\n",
        "    print(\"■　【②-A】【②-B】【②-C】の順番で再実行してみてください。\")\n",
        "    print(\"■　ファイルパス: \" + input_video_path)\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    raise IpyExit\n",
        "\n",
        "if not process_dir_name:\n",
        "    # JST生成\n",
        "    jst_delta = datetime.timedelta(hours=9)\n",
        "    now_utc = datetime.datetime.utcnow()\n",
        "    now_jst = now_utc + jst_delta\n",
        "    formatted_jst = now_jst.strftime('%Y%m%d_%H%M%S')\n",
        "\n",
        "    # 新規作成の場合、新しくディレクトリ名を作成する\n",
        "    process_dir_name = f\"{os.path.basename(input_video_path).replace('.', '_')}_{formatted_jst}\"\n",
        "    process_dir_path = os.path.join(os.path.join('/content', 'output', process_dir_name))\n",
        "    os.makedirs(process_dir_path, exist_ok=True)\n",
        "\n",
        "! python py/exec_gpu.py $input_video_path $process_dir_path $block_frame_num\n",
        "\n",
        "if os.path.exists(os.path.join(process_dir_path, \"end_of_frame\")):\n",
        "    shutil.copytree(process_dir_path, os.path.join(base_dir_path, process_dir_name), dirs_exist_ok=True)\n",
        "\n",
        "    if not os.path.exists(os.path.join(process_dir_path, \"all_complete\")):\n",
        "        ! python py/exec_cpu.py $process_dir_path 30\n",
        "\n",
        "if os.path.exists(os.path.join(process_dir_path, \"all_complete\")):\n",
        "    # 結果をGoogleドライブにコピー\n",
        "    output_path = os.path.join(base_dir_path, f\"{process_dir_name}_complete\")\n",
        "    os.makedirs(output_path, exist_ok=True)\n",
        "\n",
        "    output_original_json_path = os.path.join(output_path, \"json\", \"original\")\n",
        "    os.makedirs(output_original_json_path, exist_ok=True)\n",
        "\n",
        "    output_smooth_json_path = os.path.join(output_path, \"json\", \"smooth\")\n",
        "    os.makedirs(output_smooth_json_path, exist_ok=True)\n",
        "\n",
        "    # original.json\n",
        "    for json_path in glob(os.path.join(process_dir_path, \"*_original.json\")):\n",
        "        json_file_name = os.path.basename(json_path)\n",
        "        shutil.copy(json_path, os.path.join(output_original_json_path, json_file_name))\n",
        "\n",
        "    # smooth.json\n",
        "    for json_path in glob(os.path.join(process_dir_path, \"*_smooth.json\")):\n",
        "        json_file_name = os.path.basename(json_path)\n",
        "        shutil.copy(json_path, os.path.join(output_smooth_json_path, json_file_name))\n",
        "\n",
        "    # visualize.html\n",
        "    shutil.copy(\"/content/mmd-auto-trace-4/data/vis/visualize.html\", os.path.join(output_path, \"json\", \"visualize.html\"))\n",
        "\n",
        "    output_full_motion_path = os.path.join(output_path, \"motion\", \"full\")\n",
        "    os.makedirs(output_full_motion_path, exist_ok=True)\n",
        "\n",
        "    output_reduce_wide_motion_path = os.path.join(output_path, \"motion\", \"reduce_wide\")\n",
        "    os.makedirs(output_reduce_wide_motion_path, exist_ok=True)\n",
        "\n",
        "    output_reduce_narrow_motion_path = os.path.join(output_path, \"motion\", \"reduce_narrow\")\n",
        "    os.makedirs(output_reduce_narrow_motion_path, exist_ok=True)\n",
        "\n",
        "    # vmd\n",
        "    for vmd_path in glob(os.path.join(process_dir_path, \"*_full.vmd\")):\n",
        "        vmd_name = os.path.basename(vmd_path)\n",
        "        shutil.copy(vmd_path, os.path.join(output_full_motion_path, vmd_name))\n",
        "\n",
        "    for vmd_path in glob(os.path.join(process_dir_path, \"*_reduce_wide.vmd\")):\n",
        "        vmd_name = os.path.basename(vmd_path)\n",
        "        shutil.copy(vmd_path, os.path.join(output_reduce_wide_motion_path, vmd_name))\n",
        "\n",
        "    for vmd_path in glob(os.path.join(process_dir_path, \"*_reduce_narrow.vmd\")):\n",
        "        vmd_name = os.path.basename(vmd_path)\n",
        "        shutil.copy(vmd_path, os.path.join(output_reduce_narrow_motion_path, vmd_name))\n",
        "\n",
        "    output_model_path = os.path.join(output_path, \"model\")\n",
        "\n",
        "    # pmx\n",
        "    shutil.copytree(\"/content/mmd-auto-trace-4/data/pmx/tex/\", os.path.join(output_model_path, \"tex\"), dirs_exist_ok=True)\n",
        "    shutil.copy(\"/content/mmd-auto-trace-4/data/pmx/v4_trace_model.pmx\", os.path.join(output_model_path, \"v4_trace_model.pmx\"))\n",
        "    shutil.copy(\"/content/mmd-auto-trace-4/data/pmx/v4_trace_model_red.pmx\", os.path.join(output_model_path, \"v4_trace_model_red.pmx\"))\n",
        "    shutil.copy(\"/content/mmd-auto-trace-4/data/pmx/v4_trace_model_blue.pmx\", os.path.join(output_model_path, \"v4_trace_model_blue.pmx\"))\n",
        "    shutil.copy(\"/content/mmd-auto-trace-4/data/pmx/v4_trace_model_green.pmx\", os.path.join(output_model_path, \"v4_trace_model_green.pmx\"))\n",
        "\n",
        "    # readme\n",
        "    shutil.copy(os.path.join(\"/content/mmd-auto-trace-4/data/txt/readme_ja.txt\"), os.path.join(output_path, \"readme.txt\"))\n",
        "\n",
        "    ! sleep 10\n",
        "\n",
        "    play_sound(SoundType.COMPLETE)\n",
        "\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    print(\"■　* COMPLETE *\")\n",
        "    print(\"■　全ての自動トレース処理が完了しました\")\n",
        "    print(f\"■　Googleドライブ上の「{process_dir_name}_complete」フォルダをダウンロードして確認してください\")\n",
        "    print(f\"■　ダウンロード完了後、Googleドライブ上の 「{process_dir_name}」「{process_dir_name}_complete」フォルダは削除していただいて構いません\")\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "\n",
        "else:\n",
        "    shutil.copytree(process_dir_path, os.path.join(base_dir_path, process_dir_name), dirs_exist_ok=True)\n",
        "\n",
        "    ! sleep 10\n",
        "\n",
        "    play_sound(SoundType.SUCCESS)\n",
        "\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n",
        "    print(\"■　* PROCESS *\")\n",
        "    print(\"■　自動トレース処理が途中まで終わりました\")\n",
        "    print(\"■　まだGPUが使える場合は、このセルを再実行してください\")\n",
        "    print(\"■　GPUを使い切った場合は、一旦作業を中断し、後日①-Aから再度実行してください\")\n",
        "    print(f\"■　Googleドライブ上の作業フォルダ ({process_dir_name}) はまだ削除しないでください\")\n",
        "    print(\"■■■■■■■■■■■■■■■\")\n"
      ],
      "metadata": {
        "id": "Q32Z-oOqlZLd",
        "cellView": "form"
      },
      "execution_count": null,
      "outputs": []
    }
  ]
}